The Tomato Spotted Wilt Virus data comes from an experimental greenhouse epidemic conducted by Hughes et. al. This data was processed and made available through the EpiILM R package.
The experiment consisted of 520 individual tomato uniformly spaced in a 10 x 26m greenhouse. Every 2 weeks it was determined if an individual plant was infected or not. Our analysis follows from day 42 onward.
Hughes, G., McRoberts, N., Madden, L.V., Nelson, S.C., 1997. Validating math-ematical models of plant-disease progress in space and time. MathematicalMedicine and Biology: A Journal of the IMA 14, 85–112.
Warriyar K.V., V., Deardon, R., 2018. EpiILM: Spatial and Network Based Individual Level Models for Epidemics. URL: https://CRAN.R-project.org/package=EpiILM. R package version 1.4.2.
In [1]:
using CSV, DelimitedFiles, Distances, Random, Pathogen, Plots
Random.seed!(5432)
# POPULATION INFOFORMATION
# Use CSV.jl for DataFrames I/O
# We know the types of the columns, so we'll manually specify those.
# * Individual IDs are `Int64`
# * X,Y coordinates are `Float64`s
risks = CSV.read(joinpath(@__DIR__, "plant_locations.csv"), types=[Int64; Float64; Float64])
# Will precalculate distances
distances = [euclidean([risks[i, :x]; risks[i, :y]], [risks[j, :x]; risks[j, :y]]) for i = 1:size(risks, 1), j = 1:size(risks, 1)]
pop = Population(risks, distances)
Out[1]:
In [2]:
# OBSERVATIONS
# Use julia's included CSV interface for simple vector of observation times
raw_observations = readdlm(joinpath(@__DIR__, "infection_observations.csv"))[:]
# Create an `EventObservations` object with `Pathogen.jl`
obs = EventObservations{SI}(raw_observations)
# For performing inference we are going to set everything at or before t = 42 as being the starting state.
starting_states = [obs.infection[i] <= 42.0 ? State_I : State_S for i=1:obs.individuals]
# We will also set these observation times to -Inf
obs.infection[obs.infection .<= 42.0] .= -Inf
obs
Out[2]:
In [3]:
# RISK FUNCTIONS
function _zero(params::Vector{Float64}, pop::Pathogen.Population, i::Int64)
return 0.0
end
function _one(params::Vector{Float64}, pop::Pathogen.Population, i::Int64)
return 1.0
end
function _powerlaw(params::Vector{Float64}, pop::Pathogen.Population, i::Int64, k::Int64)
α = params[1]
β = params[2]
d = pop.distances[k, i]
return α * (d^(-β))
end
rf = RiskFunctions{SI}(_zero, # sparks function - we will assume no exogenous transmissions and set this to zero
_one, # susceptibility function - we do not have individual level risk factor information to explore here, so will set to a constant 1
_powerlaw, # transmissability function - we will use a powerlaw (with intercept) kernel. This provides a spatial and non-spatial component to infection transmissions. This has 3 parameters.
_one) # infectivity function - we do not have individual level risk factor information to explore here, so will set to a constant 1
Out[3]:
In [4]:
rpriors = RiskPriors{SI}(UnivariateDistribution[], # empty `UnivariateDistribution` vector for all parameter-less functions
UnivariateDistribution[],
[Gamma(1.0, 0.5); Gamma(1.0, 1.0)], # Relatively uninformative priors with appropriate support
UnivariateDistribution[])
ee = EventExtents{SI}(14.0)
mcmc = MCMC(obs, ee, pop, starting_states, rf, rpriors)
start!(mcmc, attempts = 50000)
iterate!(mcmc, 50000, 2.0, event_batches = 20)
Out[4]:
In [5]:
#using JLD2
#@save "mcmc.jld2" mcmc
#@load "mcmc.jld2" mcmc
In [20]:
gr(dpi=200)
Out[20]:
In [21]:
p1 = plot(1:20:50001, mcmc.markov_chains[1].risk_parameters, yscale=:log10, size=(400,300))
png(p1, joinpath(@__DIR__, "trace.png"))
In [24]:
summary(mcmc, burnin=10000, thin=20)
Out[24]:
In [8]:
tnd = TNDistribution(mcmc, burnin=10000, thin=20)
Out[8]:
In [27]:
p2 = plot(tnd, size=(400,300))
png(p2, joinpath(@__DIR__, "posterior_outdegree.png"))
In [28]:
p3 = plot(tnd, pop, size=(500,250));
In [29]:
png(p3, joinpath(@__DIR__, "posterior_tn.png"))
In [30]:
p4 = plot(mcmc.markov_chains[1].events[10000], State_S,
linealpha=0.01, title="S", xguidefontsize=8, yguidefontsize=8,
xtickfontsize=7, ytickfontsize=7, titlefontsize=11)
for i=10050:20:50000
plot!(p4, mcmc.markov_chains[1].events[i], State_S, linealpha=0.02)
end
p5 = plot(mcmc.markov_chains[1].events[10000], State_I,
linealpha=0.01, title="I", xguidefontsize=8, yguidefontsize=8, xtickfontsize=7, ytickfontsize=7, titlefontsize=11)
for i=10050:20:50000
plot!(p5, mcmc.markov_chains[1].events[i], State_I, linealpha=0.02)
end
plot!(p5, obs, State_I, linecolor=:black, linewidth=1.5) # Show infection observations (day of prodrome)
l = @layout [a b]
combinedplots1 = plot(p4, p5, layout=l, link=:y, size=(800,400))
png(combinedplots1, joinpath(@__DIR__, "posterior_epi_curves.png"))